<?php

declare(strict_types=1);

namespace App\Service;

use App\Constants\ErrorCode;
use App\Exception\BusinessException;
use App\Model\AppUserCashAccount;
use App\Model\FlyOrderCommission;
use Hyperf\Database\Model\Builder;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;

/**
 * 用户提现服务
 * Class AdvanceWithdrawService
 * @package App\Service
 */
class AdvanceWithdrawService extends BaseService
{
    const STATUS_WAIT_CHECK = 1; // 待审核
    const STATUS_CHECKED = 2; // 审核通过
    const STATUS_REFUSED = 3; // 被驳回

    const TYPE_USER = 1; // 用户
    const TYPE_SHOP_SELL = 2; // 商家销售
    const TYPE_SHOP_CASH = 3; // 商家保证金

    /**
     * @Inject
     * @var FlyShopService
     */
    private $shop;

    /**
     * 申请提现
     * @param int $user_id 用户ID
     * @param int $type 提现类型： 1用户账户提现 2商家销售额提现 3商家保证金提现
     * @param float $amount 提现金额
     * @param string $draw_type 收款账户类型
     * @return bool
     */
    public function apply(int $user_id, int $type, float $amount, string $draw_type): bool
    {
        $params = $this->getWithDrawParams($user_id, $type, $amount, $draw_type);
        Db::beginTransaction();
        try {
            $instance = $this->getModelInstance();
            foreach ($params as $field => $val) {
                $instance->$field = $val;
            }
            if (!$instance->save()) {
                Db::rollBack();
                throw new BusinessException(ErrorCode::NORMAL_ERROR, '申请失败');
            }
            $cash_instance = make(AppUserCashAccount::class)->find($params['cash_account_id']);
            $cash_instance->amount_total_out = Db::raw("amount_total_out+" . $amount);
            $cash_instance->update_time = time();
            if (!$cash_instance->save()) {
                Db::rollBack();
                throw new BusinessException(ErrorCode::NORMAL_ERROR, '操作失败');
            }

        } catch (\Throwable $exception) {
            Db::rollBack();
            throw new BusinessException(ErrorCode::NORMAL_ERROR, $exception->getMessage());
        }
        Db::commit();
        return true;
    }

    /**
     * 获取提现参数
     * @param int $user_id
     * @param int $type
     * @param float $amount
     * @param string $draw_type
     * @return array
     */
    public function getWithDrawParams(int $user_id, int $type, float $amount, string $draw_type): array
    {
        $shop = ($type == self::TYPE_USER) ? [] : $this->shop->getMyShop($user_id);
        if ($type != self::TYPE_USER && (empty($shop) || (
                    (empty($shop['shop_type']) || !in_array($shop['shop_state'], [1, 2])) &&
                    (empty($shop['food_switch']) || !in_array($shop['food_state'], [1, 2]))
                ))) {
            throw new BusinessException(ErrorCode::NORMAL_ERROR, '无法申请，店铺状态异常');
        }
        $params = [
            'user_id' => $user_id,
            'cash_account_id' => 0,
            'status' => self::STATUS_WAIT_CHECK,
            'draw_start_time' => 0,
            'draw_end_time' => time(),
            'amount' => $amount,
            'create_time' => time(),
            'draw_type' => $draw_type,
            'user_type' => $type
        ];
        // 提现时间区间: 上次提现时间 至 当前时间
        $params['draw_start_time'] = $this->getModelInstance()
            ->where(['user_id' => $user_id, 'user_type' => $type, 'status' => self::STATUS_CHECKED])
            ->orderBy('create_time', 'desc')
            ->value('draw_end_time');// null = last_end_time => 首次提现

        $cash_account = make(AppUserCashAccount::class)
            ->where('surplus', '>', $amount)
            ->where(['user_id' => $user_id, 'account_type' => $type])
            ->first();
        if (empty($cash_account)) {
            throw new BusinessException(ErrorCode::NORMAL_ERROR, '可提现金额不足');
        }
        // 首次提现统计开始时间
        if (empty($params['draw_start_time'])) {
            $params['draw_start_time'] = $cash_account->create_time;
        }
        return $params;
    }

    /**
     * 提现申请列表
     * @param int $type
     * @return Builder
     */
    public function getApplyList(int $type): Builder
    {
        return $this->getModelInstance()->where(['type' => $type]);
    }

    /**
     * 状态数量
     * @param int $type
     * @return array
     */
    public function statStateCount(int $type = self::TYPE_USER): array
    {
        return $this->getModelInstance()
            ->where('type', '=', $type)
            ->select("count(if(status=1,1,0)) as wait_check_num,
            count(if(status=2,1,0) as checked_num),
            count(if(status=3,1,0) as refused_num)")
            ->first()->toArray();
    }

}